//
// Created by LiuYou on 2021/10/23.
//

#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <cstring>
#include <csignal>
#include "TBF.hpp"


static int srcFd;
static Tbf* tbf;

//static const int CPS = 1024;
static volatile int tokens = 0;
//static const int BURST = 1024 * 10;


static void releaseFd() {
    close( srcFd );

    const char str[] = "释放文件描述符。\n.";
    write( STDOUT_FILENO, str, sizeof( str ) - 1 );
}


static void releaseTbf() {
    destroyTbf( tbf );
}


/**
 * @brief 这个 main函数 是完全模拟这个库的使用者即用户的各种需求操作
 *
 * @details 即这个就是用来测试库的。。
 */
int main(int argc, char** argv) {


    srcFd = open( argv[1], O_RDONLY );
    atexit( releaseFd );

    tbf = makeTbf( 10, 100 );
    if (tbf == nullptr) {
        fprintf( stderr, "makeTbf();执行失败。\n" );
        exit( 1 );
    }
    atexit( releaseTbf );


    /*
     * 定时循环。
     */
    char buffer[1024]{};
    ssize_t readBytes{};


    while (true) {

        int fetchTokens = fetchToken( tbf, 1024 );
        if (fetchTokens < 0) {
            fprintf( stderr, "fetchToken();调用失败。\n" );
            exit( 1 );
        }

//        readBytes = read( srcFd, buffer, sizeof( buffer ));
        readBytes = read( srcFd, buffer, fetchTokens );
        if (readBytes < 0) {
            perror( "read()" );
            exit( 1 );
        }
        if (readBytes == 0) {
            break;
        }

        if (fetchTokens - readBytes > 0) {
            returnToken( tbf, fetchTokens - static_cast<int>(readBytes));
        }

        ssize_t writeBytes{};
        int writePos{};
        while ((writeBytes = write( STDOUT_FILENO, buffer + writePos, readBytes )) != readBytes) {
            writePos += static_cast<int>(writeBytes);
            readBytes -= writePos;
        }


    }


    return 0;
}


#ifdef origin

#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <cstring>
#include <csignal>


static int srcFd;

static const int CPS = 1024;
static volatile int tokens = 0;
static const int BURST = 100;


static void releaseResources() {
    close( srcFd );

    const char str[] = "释放文件描述符。\n.";
    write( STDOUT_FILENO, str, sizeof( str ) - 1 );
}


/**
 * @brief 这个 main函数 是完全模拟这个库的使用者即用户的各种需求操作
 *
 * @details 即这个就是用来测试库的。。
 */
int main(int argc, char** argv) {


    srcFd = open( argv[1], O_RDONLY );
    atexit( releaseResources );


    /*
     * 定时循环。
     */
    char buffer[CPS]{};
    ssize_t readBytes{};

    // todo 笔记: 阻塞的系统调用会被信号打断。
    while ((readBytes = read( srcFd, buffer, sizeof( buffer ))) != 0) {
        if (readBytes < 0) {
            perror( "read()" );
            exit( 1 );
        }
        ssize_t writeBytes{};
        int writePos{};
        while ((writeBytes = write( STDOUT_FILENO, buffer + writePos, readBytes )) != readBytes) {
            writePos += static_cast<int>(writeBytes);
            readBytes -= writePos;
        }


    }


    return 0;
}

#endif
